'use strict';

/**
 * Redis 订阅实现的推送
 */
const redis = require('redis');
const globalConfig = require('../../config/global_config');
const redisOptions = globalConfig.redis;
const logger = require('../utils/logger');

const client = redis.createClient(redisOptions);

const onReadyCallbacks = [];
const onErrorCallbacks = [];
const onQuitCallbacks = [];
const onSubscribeCallbacks = [];
const onMsgCallbacks = [];
const onUnsubscribeCallbacks = [];
const filters = [];

// client.auth("");
function init(callbacks) {
    add_callback(callbacks);
    // 客户端连接redis成功后执行回调
    client.on("ready", async function () {
        logger.logInfo("\n" + '===== Redis Ready - ' + "\n");
        for (let i = 0; i < onReadyCallbacks.length; ++i) {
            await onReadyCallbacks[i]();
        }
    });

    client.on("error", async function (error) {
        logger.logError("\n" + '===== Redis Error - ' + error + "\n");
        for (let i = 0; i < onErrorCallbacks.length; ++i) {
            await onErrorCallbacks[i](error);
        }
    });

    client.on("end", async function () {
        logger.logInfo("\n" + '===== Redis End - ' + "\n");
        for (let i = 0; i < onQuitCallbacks.length; ++i) {
            await onQuitCallbacks[i]();
        }
    });

    // 监听订阅成功事件
    client.on("subscribe", async function (channel, count) {
        logger.logInfo("\n" + '===== Redis client subscribed to '
            + channel + ", " + count + " total subscriptions");
        for (let i = 0; i < onSubscribeCallbacks.length; ++i) {
            await onSubscribeCallbacks[i](channel, count);
        }
    });

    // 收到消息后执行回调，message是redis发布的消息
    client.on("message", async function (channel, message) {
        logger.logInfo("\n" + '===== Redis Message - Channel:' + channel
            + ' message:' + message + "\n");
        try {
            message = JSON.parse(message);
            let filter = false;
            for (let i = 0; i < filters.length && !filter; ++i) {
                message = await filters[i](channel, message);
            }

            for (let i = 0; i < onMsgCallbacks.length; ++i) {
                await onMsgCallbacks[i](channel, message);
            }
        } catch (error) {
            logger.logError("\n" + '===== Redis received error - ' + err + ' =====' + "\n");
        }
    });

    // 监听取消订阅事件
    client.on("unsubscribe", async function (channel, count) {
        logger.logInfo("\n" + '===== Redis client unsubscribed from ' + channel
            + ", " + count + " total subscriptions");
        for (let i = 0; i < onUnsubscribeCallbacks.length; ++i) {
            await onUnsubscribeCallbacks[i](channel, count);
        }
    });
}

/**
 *
 * @param {[callbacks]} callbacks
 */
function add_callback(callbacks) {
    for (let i = 0; i < callbacks.length; ++i) {
        let callback = callbacks[i];
        if (callback.ready_callback != undefined) {
            logger.logInfo("\n" + '===== Redis AddCallback - ' + " ready" + "\n");
            onReadyCallbacks.push(callback.ready_callback);
        }
        if (callback.error_callback != undefined) {
            onErrorCallbacks.push(callback.error_callback);
        }
        if (callback.quit_callback != undefined) {
            onQuitCallbacks.push(callback.quit_callback);
        }
        if (callback.subscribe_callback != undefined) {
            onSubscribeCallbacks.push(callback.subscribe_callback);
        }
        if (callback.msg_callback != undefined) {
            onMsgCallbacks.push(callback.msg_callback);
        }
        if (callback.unsubscribe_callback != undefined) {
            onUnsubscribeCallbacks.push(callback.unsubscribe_callback);
        }
    }
}

/**
 * @param {filter} filter
 */

function add_filter(filter) {
    filters.push(filter);
}

function quit() {
    client.quit();
}

/**
 * 订阅
 * @param channel
 */
function subscribe(channel) {
    client.subscribe(channel);
}

/**
 * 取消订阅
 * @param channel
 */
function unsubscribe(channel) {
    client.unsubscribe(channel);
}


exports.init = init;
exports.add_callback = add_callback;
exports.add_filter = add_filter;
exports.quit = quit;
exports.subscribe = subscribe;
exports.unsubscribe = unsubscribe;
